import threading
import time
from ac import models
from django.db.transaction import atomic
from django.db import connection
from method import tools


class Function(object):

    @atomic()
    def create_function(self, PID, func_list):
        """
        接收一个PID与Function List，返回这个功能的创建结果，一个列表形式的功能名称。创建不成功则抛出异常
        :param PID:
        :param func_list:
        :return:
        """
        project_obj = models.Project.objects.filter(PID=PID)[0]
        count = []
        for func in func_list:
            result, status = models.Function.objects.get_or_create(
                func_name=func["func_name"],
                func_desc=func["desc"],
                project=project_obj,
                parent=models.Function.objects.filter(func_name__iexact=func["parent_name"])
            )
            if status:
                count.append(func["func_name"])
            else:
                raise ValueError("功能 '%s' 已存在" % func["func_name"])
                # return False, "function: '%s' already exist" % func["func_name"]
        return True, "成功創建: %s" % str(count)


class MyThread(threading.Thread):

    def __init__(self, pk):
        threading.Thread.__init__(self)
        self.pk = pk

    def run(self):
        global data
        obj = models.Function.objects.filter(parent_id=self.pk)
        for o in obj:
            data.append(o)
            thread = MyThread(o.pk)
            thread.start()


class ChildFuncAll(object):
    def __init__(self, pk):
        self.pk = pk

    def get_child(self):
        global data
        data = []
        obj = models.Function.objects.filter(parent_id=self.pk)
        if obj:
            for child in obj:
                data.append(child)
                thread = MyThread(child.pk)
                thread.start()
            time.sleep(1)
            return data
        else:
            return data

    # def __delete__(self):
    #     global data
    #     data = []


def thread(*args):
    global data
    l = []
    lock2 = threading.Lock
    lock2.acquire()
    obj = models.Function.objects.filter(parent_id=args[0])
    for o in obj:
        data.append(o)
        t = threading.Thread(target=thread, args=o.pk)
        t.start()
        l.append(t)
    for t in l:
        t.join()
    lock2.release()


class ChildFuncAll2(object):
    def __init__(self, pk):
        self.pk = pk

    def get_child(self):
        global data, lock
        data = []
        lock = threading.Lock
        l = []
        obj = models.Function.objects.filter(parent_id=self.pk)
        if obj:
            for child in obj:
                data.append(child)
                t = threading.Thread(target=thread, args=str(child.pk))
                t.start()
                l.append(t)
            for t in l:
                t.join()
                # thread = MyThread(child.pk)
                # thread.start()
            # time.sleep(1)
            return data
        else:
            return data

    # def __delete__(self):
    #     global data
    #     data = []


# class GetChildFunc(object):
#     def __init__(self):
#         self.data = []
#
#     def _get_child(self, pk):
#         # print(self.data)
#         obj = models.Function.objects.filter(parent_id=pk)
#         for child in obj:
#             self.data.append(child)
#             return self._get_child(child.pk)
#         # return self.data
#
#     def __del__(self):
#         self.data = []


class Role(object):
    def __init__(self, role, new_func):
        if not isinstance(role, int):
            role = eval(role)
            if isinstance(role, list):
                self.role = tools.list_str_to_int(role)[0]
            else:
                self.role = int(role)
        else:
            self.role = role

        if isinstance(new_func, str):                       # 如果新的功能列表是字符串类型，那么先转换为列表类型
            new_func = eval(new_func)

        self.new_func = tools.list_str_to_int(new_func)     # 初始化为数字列表类型（默认http传递的是str类型）

    def check_function(self):
        self.cursor = connection.cursor()
        self.cursor.execute("SELECT function_id FROM tb_role_function_map WHERE role_id=%s" % str(self.role))
        self.old_func = [func[0] for func in self.cursor.fetchall()]  # 初始化为列表类型（SQL语句查询结果为二元元祖类型）

        if not list(set(self.old_func).difference(set(self.new_func))) \
                and not list(set(self.new_func).difference(set(self.old_func))):
            # 检查新旧两个功能ID的列表是否存在差集，两个差集都为空表示两个列表完全相同
            return False
        else:
            return True

    def add_role_function(self):
        """
        接收角色和功能的ID参数，Role只能是一个ID参数，Function可以是一个ID的列表
        :param role: Role ID
        :param function: Function ID  or  Function ID List
        :return:
        """
        exist = []
        succeed = []
        for func in self.new_func:
            obj, status = models.RoleFunctionMap.objects.get_or_create(role_id=self.role, function_id=func)
            if status:
                succeed.append(func)
            else:
                exist.append(func)
        if exist:
            return "exist: '%s',succeed: '%s'" % (str(exist), str(succeed))
        else:
            return "succeed: '%s'" % str(succeed)

    def update_role_function(self):
        """
        接收角色和功能的ID参数，Role只能是一个ID参数，Function可以是一个ID的列表
        这里
        :param role: Role ID
        :param new_func: 新的功能ID列表
        :return:
        """
        if not self.check_function():
            return "當前數據不需要更新!"

        delete = list(set(self.old_func).difference(set(self.new_func)))      # 获取旧的有的，新的却没有的，等待删除
        create = list(set(self.new_func).difference(set(self.old_func)))      # 获取新的有的，旧的却没有的，等待添加

        if len(delete) == len(create):                              # 新旧功能列表长度相同则不需要补齐，否则补None
            pass
        elif len(delete) > len(create):
            tools.supplying_list(create, len(delete) - len(create))
        else:
            tools.supplying_list(delete, len(create) - len(delete))
        for old, new in zip(delete, create):
            if old:
                func_obj = models.RoleFunctionMap.objects.filter(function_id=old, role_id=self.role)[0]
                if new:
                    if self.cursor.execute("SELECT id FROM tb_function WHERE id = %s" % new):   # 确认新功能是否存在
                        func_obj.function_id = new
                        func_obj.save()
                    else:
                        raise ValueError("功能 ID '%s' 不存在!" % new)
                else:
                    func_obj.delete()       # 旧的存在新的却没有，代表被取消的功能，执行删除
            else:
                if self.cursor.execute("SELECT id FROM tb_function WHERE id = %s" % new):       # 确认新功能是否存在
                    models.RoleFunctionMap.objects.create(role_id=self.role, function_id=new)
                else:
                    raise ValueError("功能 ID '%s' 不存在!" % new)

        role_obj = models.Role.objects.filter(pk=self.role)[0]
        role_obj.func_list = self.new_func
        role_obj.save()
        return "Update successfully!"


class UserRoleUpdate(object):
    def __init__(self, head, new_role):
        if isinstance(head, str):                           # 字符串类型才需要转换
            head = eval(head)
        if isinstance(new_role, str):                       # 字符串类型才需要转换
            new_role = eval(new_role)
        if isinstance(head, list):
            self.head = tools.list_str_to_int(head)[0]      # 一对多字段的一参数
        else:
            self.head = int(head)
        self.new_role = tools.list_str_to_int(new_role)     # 初始化为数字列表类型（默认http传递的是str类型）

    def contrast(self):
        self.cursor = connection.cursor()
        self.cursor.execute("SELECT role_id FROM tb_user_role_map WHERE user_id=%s" % str(self.head))
        self.old_role = [func[0] for func in self.cursor.fetchall()]  # 初始化为列表类型（SQL语句查询结果为二元元祖类型）

        if not list(set(self.old_role).difference(set(self.new_role))) \
                and not list(set(self.new_role).difference(set(self.old_role))):
            # 检查新旧两个功能ID的列表是否存在差集，两个差集都为空表示两个列表完全相同
            return False
        else:
            return True

    def add_user_role(self):
        """
        新增用戶和角色
        """
        exist = []
        succeed = []
        for role in self.new_role:
            obj, status = models.UserRoleMap.objects.get_or_create(user_id=self.head, role_id=role)
            if status:
                succeed.append(role)
            else:
                exist.append(role)
        if exist:
            return "exist: '%s',succeed: '%s'!" % (str(exist), str(succeed))
        else:
            return "succeed: '%s'!" % str(succeed)

    def update_user_role(self):
        """
        接收角色和功能的ID参数，Role只能是一个ID参数，Function可以是一个ID的列表
        这里
        :param role: Role ID
        :param new_role: 新的功能ID列表
        :return:
        """
        if not self.contrast():
            return "Don't need to be updated!"

        delete = list(set(self.old_role).difference(set(self.new_role)))      # 获取旧的有的，新的却没有的，等待删除
        create = list(set(self.new_role).difference(set(self.old_role)))      # 获取新的有的，旧的却没有的，等待添加

        if len(delete) == len(create):                              # 新旧功能列表长度相同则不需要补齐，否则补None
            pass
        elif len(delete) > len(create):         # 把两个列表的长度对齐（补齐短的）
            tools.supplying_list(create, len(delete) - len(create))
        else:
            tools.supplying_list(delete, len(create) - len(delete))
        for old, new in zip(delete, create):
            check_role = self.cursor.execute("SELECT id FROM tb_project_role WHERE id = '%s'" % new)  # 确认新功能是否存在
            if old:
                role_obj = models.UserRoleMap.objects.filter(role_id=old, user_id=self.head)[0]
                if new:
                    if check_role:
                        role_obj.role_id = new
                        role_obj.save()
                    else:
                        raise ValueError("功能 ID '%s' 不存在!" % new)
                else:
                    role_obj.delete()       # 旧的存在新的却没有，代表被取消的功能，执行删除
            else:
                if check_role:
                    models.UserRoleMap.objects.create(user_id=self.head, role_id=new)
                else:
                    raise ValueError("功能 ID '%s' 不存在!" % new)

            # if old:
            #     role_obj = models.UserRoleMap.objects.filter(role_id=old)[0]
            #     if new:
            #         role_obj.role_id = new
            #         role_obj.save()
            #     else:
            #         role_obj.delete()       # 旧的存在新的却没有，代表被取消的功能，执行删除
            # else:
            #     models.UserRoleMap.objects.create(user_id=self.head, role_id=new)
        return "Update successfully!"